#ifndef ARMARC_HEADER
#define ARMARC_HEADER
/* (c) David Alan Gilbert 1995-1998 - see Readme file for copying info */

#include "armdefs.h"
#include "fastmap.h"

/* Memory map locations */
#define MEMORY_0x3800000_R_ROM_HIGH   0x3800000  /* Some sections of the memory map    */
#define MEMORY_0x3800000_W_LOG2PHYS   0x3800000  /* have different functions when read */
#define MEMORY_0x3400000_R_ROM_LOW    0x3400000  /* or written to.                     */
#define MEMORY_0x3600000_W_DMA_GEN    0x3600000
#define MEMORY_0x3400000_W_VIDEOCON   0x3400000

#define MEMORY_0x3000000_CON_IO       0x3000000
#define MEMORY_0x2000000_RAM_PHYS     0x2000000

typedef enum MemSize {
  MemSize_256K,
  MemSize_512K,
  MemSize_1M,
  MemSize_2M,
  MemSize_4M,
  MemSize_8M,
  MemSize_12M,
  MemSize_16M
} MemSize;

typedef void (*ARMEmuFunc)(ARMul_State *state, ARMword instr);

ARMEmuFunc ARMul_Emulate_DecodeInstr(ARMword instr);

struct MEMCStruct {
  ARMword *ROMHigh;           /* ROM high and low are to seperate rom areas */
  ARMword ROMHighMask;
  ARMword ROMHighSize;        /* For mapping in ROMs of different types eg. */
  ARMword *ROMLow;            /* 8bit Rom and 32bit Rom, or access speeds */ 
  ARMword ROMLowMask;
  ARMword ROMLowSize;
  ARMword *PhysRam;
  ARMword RAMSize;
  ARMword RAMMask;

  int32_t PageTable[512]; /* Good old fashioned MEMC1 page table */
  ARMword ControlReg;
  ARMword PageSizeFlags;
  ARMword Vinit,Vstart,Vend,Cinit;

  /* Sound buffer addresses */
  ARMword Sstart; /* The start and end of the next buffer */
  ARMword SendN;
  ARMword Sptr; /* Current position in current buffer */
  ARMword SendC; /* End of current buffer */
  ARMword SstartC; /* The start of the current buffer */
  bool NextSoundBufferValid; /* This indicates whether the next buffer has been set yet */

  uint_fast8_t ROMMapFlag; /* 0 means ROM is mapped as normal,1 means
                     processor hasn't done access to low memory, 2 means it
                     hasn't done an access to ROM space, so in 1 & 2 accesses
                     to  low mem access ROM */

  ARMword DRAMPageSize; /* Page size we pretend our DRAM is */ 

  uint32_t UpdateFlags[(512*1024)/UPDATEBLOCKSIZE]; /* One flag for
                                                       each block of DMAble RAM
                                                       incremented on a write */

  /* Fastmap memory block pointers */
  void *ROMRAMChunk;
  void *EmuFuncChunk;
};


extern struct MEMCStruct memc;

#define MEMC (memc)

bool FastMap_GetOSMode(void);

#ifdef FASTMAP_INLINE
#include "arch/fastmap.c"
#endif

/**
 * ARMul_LoadWordN
 *
 * Load Word, Non Sequential Cycle
 *
 * @param state
 * @param address
 * @returns
 */
#define ARMul_LoadWordN ARMul_LoadWordS /* These were 100% equivalent in the original implementation! */

/**
 * ARMul_StoreWordN
 *
 * Store Word, Non Sequential Cycle
 *
 * @param state
 * @param address
 * @param data
 */
#define ARMul_StoreWordN ARMul_StoreWordS /* These were 100% equivalent in the original implementation! */

/* ------------------- access routines for other sections of code ------------- */
/* Returns a byte in the keyboard serialiser tx register - or -1 if there isn't
   one. Clears the tx register full flag                                        */
int ArmArc_ReadKbdTx(ARMul_State *state);


/* Places a byte in the keyboard serialiser rx register; returns -1 if its
   still full.                                                                  */
int ArmArc_WriteKbdRx(ARMul_State *state, unsigned char value);


void ARMul_RebuildFastMap(ARMul_State *state);

#endif
